import {Injectable} from '@angular/core';
import {FormBuilder, FormGroup} from '@angular/forms';

import {BladeContainerInterface} from './blade-container.interface';
import {Blade} from './blade.model';
import {BladeService} from '../blade.service';
import {BladeData} from './blade-data';
import {DialogResult, DialogService} from '../dialog.service';
import {Command, ToolbarService} from '../toolbar.service';

import {Observable} from 'rxjs/Observable';


@Injectable()
export class BladeContainerBase<T> implements BladeContainerInterface {
  /**
   * 当前弹出层对象
   *
   * @type {Blade}
   * @memberof BladeContainerBase
   */
  currentBlade: Blade;
  /**
   * 命令集合
   *
   * @type {Command[]}
   * @memberof BladeContainerBase
   */
  commands: Command[];
  /**
   * FormGroup对象
   *
   * @type {FormGroup}
   * @memberof BladeContainerBase
   */
  formGroup: FormGroup;
  /**
   * FormBuilder对象
   *
   * @type {FormBuilder}
   * @memberof BladeContainerBase
   */
  fromBuider: FormBuilder;
  /**
   * 表单错误对象
   *
   *
   * @memberof BladeContainerBase
   */
  formErrors: any;
  /**
   * 验证信息
   *
   *
   * @memberof BladeContainerBase
   */
  validationMessages: any;

  /**
   * 设置当前实体对象
   *
   *
   * @memberof BladeContainerBase
   */
  set currentEntity(data: T) {
    this.currentBlade.currentEntity = data;
  }

  /**
   * 获取当前实体对象
   *
   * @type {*}
   * @memberof BladeContainerBase
   */
  get currentEntity(): T {
    return this.currentBlade.currentEntity;
  }

  /**
   * 获取父实体对象
   *
   * @readonly
   * @type {*}
   * @memberof BladeContainerBase
   */
  get parentEntity(): any {
    return this.currentBlade.parentEntity;
  }

  /**
   * 获取弹出层服务对象
   *
   * @readonly
   * @type {BladeService}
   * @memberof BladeContainerBase
   */
  get bladeService(): BladeService {
    return this.currentBlade.bladeService;
  }

  /**
   * 获取工具条服务对象
   *
   * @readonly
   * @type {BladeService}
   * @memberof BladeContainerBase
   */
  get toolbarService(): ToolbarService {
    return this.currentBlade.toolbarService;
  }

  /**
   * 获取弹出层数据对象
   *
   * @readonly
   * @type {BladeData}
   * @memberof BladeContainerBase
   */
  get bladeData(): BladeData {
    return this.currentBlade.bladeData;
  }

  /**
   * 获取弹出层的父对象
   *
   * @readonly
   * @type {BladeService}
   * @memberof BladeContainerBase
   */
  get parentBlade(): Blade {
    return this.currentBlade.parentBlade;
  }

  /**
   * 获取弹出层的子对象数组
   *
   * @readonly
   * @type {BladeService}
   * @memberof BladeContainerBase
   */
  get childrenBlades(): Blade[] {
    return this.currentBlade.childrenBlades;
  }

  /**
   * 获取对话框服务对象
   *
   * @readonly
   * @type {DialogService}
   * @memberof BladeContainerBase
   */
  get dialogService(): DialogService {
    return this.currentBlade.dialogService;
  }

  /**
   * 获取标示创建或者编辑对象
   *
   * @readonly
   * @type {boolean}
   * @memberof BladeContainerBase
   */
  get isNew(): boolean {
    return this.currentBlade.isNew;
  }

  /**
   * Creates an instance of BladeContainerBase.
   * @param {FormBuilder} _fromBuider 表单创建工厂
   *
   * @memberof BladeContainerBase
   */
  constructor(private _fromBuider?: FormBuilder) {
    this.fromBuider = this._fromBuider;
  }

  /**
   *
   *
   *
   * @memberof BladeContainerBase
   */
  ngOnInit(): void {
    setTimeout(() => this.bladeData.isLoading = false, 0);
    //如果没有FromBuider对象将不会去创建表单
    if (this.fromBuider != null) {
      this.setFormError();
      this.setValidationMessages();
      this.createForm();
      this.subscribeChanges();
    }
    this.registerCommand();
    this.initData();

  }

  /**
   * 初始化数据
   *
   * @returns {(any | Observable<any> | Promise<any>)}
   *
   * @memberof BladeContainerBase
   */
  initData(): any | Observable<any> | Promise<any> {
    this.formPatchValue(this.currentEntity);
  }

  /**
   * 设置表单值
   *
   * @param {*} data
   *
   * @memberof BladeContainerBase
   */
  formPatchValue(data: any) {
    if (this.formGroup != null) {
      console.log(this.currentEntity)
      this.formGroup.patchValue(this.currentEntity);
    }
  }

  /**
   * 创建表单
   *
   *
   * @memberof BladeContainerBase
   */
  createForm(): void {

  }

  /**
   * 订阅表单值变化
   *
   *
   * @memberof BladeContainerBase
   */
  subscribeChanges(): void {
    if (this.formGroup != null) {
      this.formGroup.valueChanges
        .subscribe(data => this.onValueChanged(data));
      this.formGroup.statusChanges
        .subscribe(data => this.onStatusChanged(data));
      this.formGroup.patchValue(this.currentEntity);
    }
  }


  /**
   * 表单值变化事件
   *
   * @param {any} [data]
   *
   * @memberof BladeContainerBase
   */
  onValueChanged(data?: any): void {
    if (data != null) {
      this.formGroupChanged(this.formGroup);
    }
  }

  formGroupChanged(form: FormGroup) {
    if (form != null) {
      let controls = form.controls;
      if (controls != null) {
        let controlNames = Object.getOwnPropertyNames(controls);
        controlNames.forEach(controlName => {
          if (controls[controlName] instanceof FormGroup) {
            this.formGroupChanged(controls[controlName] as FormGroup);
          }
          else {
            this.formErrors[controlName] = '';
            let messages = this.validationMessages[controlName];
            if (!controls[controlName].valid) {
              for (const key in controls[controlName].errors) {
                this.formErrors[controlName] = messages[key];
              }
            }

          }
        })
      }
    }
  }

  /**
   * 表单状态变化事件
   *
   * @param {any} [data]
   *
   * @memberof BladeContainerBase
   */
  onStatusChanged(data?: any): void {
    if (this.formGroup.status.toLowerCase() == 'invalid') {
      this.onValueChanged(data);
    }
  }

  /**
   * 注册命令
   *
   *
   * @memberof BladeContainerBase
   */
  registerCommand(): void {
    if (this.commands != null) {
      for (let i = 0; i < this.commands.length; i++) {
        this.currentBlade.toolbarService.register(this.commands[i]);
      }
    }
  }

  /**
   * 刷新
   *
   * @param {*} anyData
   *
   * @memberof BladeContainerBase
   */
  refresh(anyData: any): void {
    this.currentEntity = anyData;
    this.currentBlade.bladeData.isLoading = true;
    this.initData();
  }

  /**
   * 是否存在变更
   *
   * @returns {boolean}
   *
   * @memberof BladeContainerBase
   */
  hasChange(): boolean {
    if (this.formGroup != null) {
      let enity = this.formGroup.value;
      let names: string[] = Object.getOwnPropertyNames(enity);
      for (let i: number = 0; i < names.length; i++) {
        let name = names[i];
        if (this.currentEntity.hasOwnProperty(name)) {
          let value = Object.getOwnPropertyDescriptor(this.currentEntity, name).value;
          if (value != enity[name]) {
            return true;
          }
        }
      }
    }
    return false;
  }

  /**
   * 是否存在验证错误
   *
   * @returns {boolean}
   *
   * @memberof BladeContainerBase
   */
  hasError(): boolean {
    if (this.formGroup != null) {
      return !this.formGroup.valid;
    }
    return false;
  }

  /**
   * 保存变更
   *
   *
   * @memberof BladeContainerBase
   */
  saveChange(): Promise<boolean> {
    return Promise.resolve(true);
  }

  /**
   * 创建对象
   *
   *
   * @memberof BladeContainerBase
   */
  create(): Promise<boolean> {
    return Promise.resolve(true);
  }

  /**
   * 是否可以卸载组件
   *
   * @returns {(boolean | Promise<boolean> | Observable<boolean>)}
   *
   * @memberof BladeContainerBase
   */
  canDeactivate(): boolean | Promise<boolean> | Observable<boolean> {
    if (this.fromBuider != null && this.formGroup != null) {
      if (!this.formGroup.dirty) {
        return true;
      }
      else {
        return !this.hasChange() && !this.hasError();
      }
    }
    return true;
  }

  /**
   * 根据命令名称返回命令对象
   *
   * @param {string} commandName
   * @returns {Command}
   *
   * @memberof BladeContainerBase
   */
  getCommand(commandName: string): Command {
    return this.commands.find(o => o.name == commandName)
  }

  /**
   * 设置表单错误对象
   *
   *
   * @memberof BladeContainerBase
   */
  setFormError(): void {
  }

  /**
   * 设置表单验证信息
   *
   *
   * @memberof BladeContainerBase
   */
  setValidationMessages(): void {
  }

  /**
   * 关闭之前调用
   *
   * @returns {(boolean | Observable<boolean> | Promise<boolean>)}
   *
   * @memberof BladeContainerBase
   */
  beforeClosing(): Promise<boolean> {
    let thisBlade = this;
    return new Promise((resolve, reject) => {
      try {
        if (!thisBlade.canDeactivate()) {
          if (thisBlade.hasError()) {
            thisBlade.dialogService.showConfirmationDialog('警告', `${thisBlade.bladeData.title} 检测到错误，是否需要修改？`)
              .subscribe(dialogResult => {
                switch (dialogResult) {
                  case DialogResult.Ok:
                    resolve(false);
                    break;
                  case DialogResult.no:
                    resolve(true);
                    break;
                  case DialogResult.cancel:
                    resolve(false);
                    break;
                }
              });
          }
          else if (thisBlade.hasChange()) {
            thisBlade.dialogService.showConfirmationDialog('警告', `${thisBlade.bladeData.title} 检测到变更，是否需要${thisBlade.isNew ? '创建' : '保存'}？`)
              .subscribe(dialogResult => {
                switch (dialogResult) {
                  case DialogResult.Ok:
                    if (!this.isNew) {
                      thisBlade.saveChange().then(res => {
                        if (res) {
                          resolve(true);
                        }
                        else {
                          resolve(false);
                        }
                      });
                    }
                    else {
                      thisBlade.create().then(res => {
                        if (res) {
                          resolve(true);
                        }
                        else {
                          resolve(false);
                        }
                      });
                    }
                    break;
                  case DialogResult.no:
                    resolve(true);
                    break;
                  case DialogResult.cancel:
                    resolve(false);
                    break;
                }
              });
          }
        }
        else {
          resolve(true);
        }
      }
      catch (error) {
        reject(error);
      }
    });
  }


  /**
   * 关闭之后调用
   *
   * @returns {(void | Observable<void> | Promise<void>)}
   *
   * @memberof BladeContainerBase
   */
  closed(): Promise<any> {
    return null;
  }

}


// WEBPACK FOOTER //
// ./src/app/shared/blade/blade-container-base.ts
